﻿#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//int main()
//{
//	int* p = (int*)malloc(INT_MAX * 100);
//	if (p == NULL)
//	{
//		perror("不行");
//		return 1;
//	}
//	return 0;
//}

//char* GetMemory()
//{
//	char*p = (char*)malloc(100);
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//	return p;
//}
//void Test(void)
//{
//	char* str = NULL;
//	str=GetMemory();
//	strcpy(str, "hello world");
//	printf(str);
//	free(str);
//	str = NULL;
//}
//int main()
//{
//	Test();
//	return 0;
//}
//
//void GetMemory(char** p)
//{
//	*p = (char*)malloc(100);
//	if (*p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//}
//void Test(void)
//{
//	char* str = NULL;
//	GetMemory(&str);
//	strcpy(str, "hello world");
//	printf(str);
//	free(str);
//	str = NULL;
//}
//int main()
//{
//	Test();
//	return 0;
//}


//----------------------------------------------------
//malloc 分配内存地址，返回值为void* 记得强制类型转换，内存分配失败会返回NULL指针，所以要加判断
//用完内存记得free，然后将指针置空
//int main()
//{
//	int* p = (int*)malloc(100 * sizeof(int));
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//
//	free(p);//这里释放的是p所指向的内存空间，并没有释放掉p指针变量里存的地址，所以现在p仍然指向原来的内存地址，但该地址已经无效。p现在是野指针
//	p = NULL;//要加上这一步
//	return 0;
//}

//----------------------------------------------------
//calloc 分配内存地址，返回值为void* 记得强制类型转换，内存分配失败会返回NULL指针，所以要加判断
// 参数有两个，第一个为个数，第二个为一个元素的字节大小，一般用sizeof。
//功能比malloc多一个初始化，将内存的元素全部置零，但是效率低
//int main()
//{
//	int* p = (int*)calloc(100 , sizeof(int));
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//	for (int i = 0; i < 100; i++)
//	{
//		printf("%d:%d\n", i,p[i]);
//	}
//	free(p);//这里释放的是p所指向的内存空间，并没有释放掉p指针变量里存的地址，所以现在p仍然指向原来的内存地址，但该地址已经无效。p现在是野指针
//	p = NULL;//要加上这一步
//	return 0;
//}


//----------------------------------------------------
//realloc 第一个参数是要调整的内存地址，第二个参数是调整后的新大小。返回值为调整后的的内存起始位置
//注意 最好用新的指针变量接收地址，除非你确定那个地址不是NULL
//这个函数调整原内存空间⼤⼩的基础上，还会将原来内存中的数据移动到 新 的空间。
// realloc也能干malloc的事 realloc(NULL,40) 相当于malloc(40)
//int main()
//{
//	int* p = (int*)malloc(10 * sizeof(int));
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//	//使用 - 前5个整型的空间存放的都是5
//	int i = 0;
//	for (i = 0; i < 5; i++)
//	{
//		*(p + i) = 5;
//	}
//	
//	//重新申请20个整型空间
//	int* ptr = (int*)realloc(p, 20 * sizeof(int));//用新的指针变量接收地址
//	if (ptr == NULL) {
//		perror("realloc");
//		return 1;
//	}
//	else
//	{
//		p = ptr;
//		ptr = NULL;
//	}
//	//使用
//	for (i = 5; i < 20; i++)
//	{
//		*(p + i) = i;
//	}
//	free(p);
//	p = NULL;
//	return 0;
//}

//------------------------------------
//例子
// 
// 
//char* GetMemory(void)
//{
//    char p[] = "hello world";//栈区
//    return p;
//}
//
//void Test(void)
//{
//    char* str = NULL;
//    str = GetMemory();
//    printf(str);
//}
//
//int main()
//{
//    Test();
//    return 0;
//}

//char* GetMemory(void)
//{
//    static char p[] = "hello world";
//    return p;
//}
//
//void Test(void)
//{
//    char* str = NULL;
//    str = GetMemory();
//    printf(str);
//}
//
//int main()
//{
//    Test();
//    return 0;
//}

//void GetMemory(char** p, int num)
//{
//    *p = (char*)malloc(num);
//}
//
//void Test(void)
//{
//    char* str = NULL;
//    GetMemory(&str, 100);
//    strcpy(str, "hello");
//    printf(str);
//    //使用完后，记得释放空间
//    free(str);
//    str = NULL;
//}
//
//int main()
//{
//    Test();
//    return 0;
//}


//void Test(void)
//{
//    char* str = (char*)malloc(100);
//    strcpy(str, "hello");
//    free(str);
//    str = NULL;//不置空就会导致非法访问内存
//
//    if (str != NULL)
//    {
//        strcpy(str, "world");
//        printf(str);
//    }
//}
//
//int main()
//{
//    Test();
//    return 0;
//}

//--------------
// 柔性数组
// 
// 1.在结构体中
// 2.最后一个成员是数组
// 3.未知大小的数组
// 这个数组就是柔性数组

//• 结构中的柔性数组成员前⾯必须  ⾄少⼀个其他成员。
//• sizeof 返回的这种结构⼤⼩ 不 包括柔性数组的内存。
//• 包含柔性数组成员的结构⽤malloc()函数进⾏内存的动态分配，并且分配的内存应该⼤于结构的⼤⼩，以适应柔性数组的预期⼤⼩。

//struct S
//{
//	int a;
//	char arr[0];
//};
//
//int main()
//{
//	printf("sizeof(struct S) = %zd\n", sizeof(struct S));
//	struct S* p = (struct S*)malloc(sizeof(struct S) + 5 * sizeof(int));
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//	p->a = 10;
//	for (int i = 0; i < 5; i++)
//	{
//		p->arr[i] = i + 1;
//	}
//
//	struct S* ptr = (struct S*)realloc(p, sizeof(struct S) + 20 * sizeof(int));
//	if (ptr == NULL)
//	{
//		perror("ralloc");
//		return 1;
//	}
//	else
//	{
//		p = ptr;
//		ptr = NULL;
//	}
//	for (int i = 5; i < 20; i++)
//	{
//		p->arr[i] = i + 1;
//	}
//	for (int i = 0; i < 20; i++)
//	{
//		printf("%d ", p->arr[i]);
//	}
//	free(p);
//	p = NULL;
//	return 0;
//}

//typedef struct S
//{
//	int a;
//	int* arr;
//}M;
//int main()
//{
//	M* p = (M*)malloc(sizeof(M));
//	if (p == NULL)
//	{
//		perror("malloc");
//		return 1;
//	}
//	p->arr = (int*)malloc(5 * sizeof(int));
//
//	for (int i = 0; i < 5; i++)
//	{
//		p->arr[i] = i + 1;
//	}
//
//	int* ptr = (int*)realloc(p->arr, 20 * sizeof(int));
//	if (ptr == NULL)
//	{
//		perror("ralloc");
//		return 1;
//	}
//	else
//	{
//		p->arr = ptr;
//		ptr = NULL;
//	}
//
//	for (int i = 5; i < 20; i++)
//	{
//		p->arr[i] = i + 1;
//	}
//
//	for (int i = 0; i < 20; i++)
//	{
//		printf("%d ", p->arr[i]);
//	}
//
//	free(p->arr);
//	p->arr = NULL;
//
//	free(p);
//	p = NULL;
//	return 0;
//}




















//int main()
//{
//	char arr[20] = "hello world";
//	for (int i = 0; i < 15; i++)
//	{
//		printf("%c ", arr[i]);
//	}
//	arr[0] = 'W';//如果将其用作字符数组的初始值，它会被复制到栈上，可以修改。
//	for (int i = 0; i < 15; i++)
//	{
//		printf("%c ", arr[i]);
//	}
//	printf("\n");
//	char* ptr = "HELLO WORLD";
//	for (int i = 0; i < 15; i++)
//	{
//		printf("%c ", ptr[i]);
//	}
//	ptr[1] = 'w';
//	for (int i = 0; i < 15; i++)
//	{
//		printf("%c ", ptr[i]);
//	}
//	//如果直接使用 "hello world"，它存储在只读内存中，不可修改。
//
//	
//	return 0;
//}